package com.zhike.service.im.manager;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Component;

import com.google.gson.Gson;
import com.zhike.common.dto.GroupInfo4Cache;
import com.zhike.common.dto.GroupMember4Cache;
import com.zhike.common.dto.MsgBody4Group;
import com.zhike.common.dto.UserProtocalsType;
import com.zhike.common.model.ChatSession;
import com.zhike.common.model.Device;
import com.zhike.common.vo.UserInfo4Cache;
import com.zhike.component.BeanAccessor;
import com.zhike.mobileimsdk.server.protocal.Protocal;
import com.zhike.service.messages.IChatSessionService;
import com.zhike.utils.MessageHelper;
import com.zhike.utils.MessageHelper.SendResultObserver;
import com.zhike.utils.cache.GroupsInfoCacheProvider;
import com.zhike.utils.cache.GroupsMembersCacheProvider;
import com.zhike.utils.cache.UsersInfoCacheProvider;
import com.zhike.utils.manager.UsersStatusManager;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public abstract class GroupMessageManager extends MessageManager {

    private String groupId;

    private String groupName;

    public GroupMessageManager(String groupId, String groupName) {
        this.groupId = groupId;
        this.groupName = groupName;
    }

    public List<String> addTargetDevices() {
        return new ArrayList<>();
    };

    /**
     * 群成员设备列表，只发给在线的设备
     */
    public List<String> targetDevices() {
        List<String> deviceNoList = new ArrayList<>();
        GroupsMembersCacheProvider groupsMembersCacheProvider = BeanAccessor.getBean(GroupsMembersCacheProvider.class);
        ConcurrentHashMap<String, GroupMember4Cache> members = groupsMembersCacheProvider.get(groupId);
        Set<String> keySet = members.keySet();
        UsersInfoCacheProvider usersInfoCacheProvider = BeanAccessor.getBean(UsersInfoCacheProvider.class);
        UsersStatusManager usersStatusManager = BeanAccessor.getBean(UsersStatusManager.class);
        for (String uid : keySet) {
            UserInfo4Cache uc = usersInfoCacheProvider.get(uid);
            List<Device> deviceList = uc.getDeviceList();
            for (Device device : deviceList) {
                if (usersStatusManager.isOnline(device.getDeviceNo())) {
                    deviceNoList.add(device.getDeviceNo());
                }
            }
        }

        return deviceNoList;
    }

    /**
     * 构建群推送消息体
     * 
     * @param root
     * @return
     */
    public String buildGroupBody(MsgBody4Group root) {
        return new Gson().toJson(root);
    };

    /**
     * 构建通知消息体
     * 
     * @param p
     * @return
     */
    public String buildNotificationBody() {
        return "";
    }

    public List<GroupMember4Cache> targetDevicesForNotify() {
        return new ArrayList<>();
    }

    /**
     * 更新消息通知数
     */
    public void updateNotifyCount(int count) {
        IChatSessionService chatSessionService = BeanAccessor.getBean(IChatSessionService.class);
        List<String> uids = new ArrayList<>();
        for (GroupMember4Cache member : targetDevicesForNotify()) {
            uids.add(member.getUserUid());
        }

        chatSessionService.updateNotifyCount(groupId, uids, count);
    }

    /**
     * 群发消息
     */
    public void sendMessagToGroup(StorageMessage storageMessage) throws Exception {
        MsgBody4Group root = new MsgBody4Group();
        root.setCy(2);// 群聊
        String message = buildGroupBody(root);

        if (storageMessage != null) {
            if (!storageMessage.store(groupId, groupName, root)) {
                return;
            }
        }

        List<String> deviceNos = targetDevices();
        UsersStatusManager usersStatusManager = BeanAccessor.getBean(UsersStatusManager.class);
        MessageHelper mh = BeanAccessor.getBean(MessageHelper.class);
        for (String deviceNo : deviceNos) {
            SendResultObserver sendResultObserver = new SendResultObserver() {
                @Override
                public void update(boolean code, Protocal p) {
                    if (code) {
                        log.info("群 {} 发送成功 {}", groupId, root.getM());
                    }
                }
            };

            if (usersStatusManager.isOnline(deviceNo)) {
                mh.sendMessage(deviceNo, message, true,
                        UserProtocalsType.MT45_OF_GROUP$CHAT$MSG_SERVER$TO$B, sendResultObserver);
            }
        }
    }

    public void notificationToGroup(int typeu, int count) throws Exception {

        String message = buildNotificationBody();
        SendResultObserver notifyResultObserver = new SendResultObserver() {
            @Override
            public void update(boolean code, Protocal p) {
                if (code) {
                    log.info("群通知 {} 发送成功 {}", groupId, p.getDataContent());
                }
            }
        };
        MessageHelper mh = BeanAccessor.getBean(MessageHelper.class);
        UsersStatusManager usersStatusManager = BeanAccessor.getBean(UsersStatusManager.class);
        UsersInfoCacheProvider usersInfoCacheProvider = BeanAccessor.getBean(UsersInfoCacheProvider.class);

        for (GroupMember4Cache member : targetDevicesForNotify()) {
            UserInfo4Cache uc = usersInfoCacheProvider.get(member.getUserUid());
            for (Device device : uc.getDeviceList()) {
                if (usersStatusManager.isOnline(device.getDeviceNo())) {
                    mh.sendMessage(device.getDeviceNo(), message, true, typeu, notifyResultObserver);
                }
            }
        }

        IChatSessionService chatSessionService = BeanAccessor.getBean(IChatSessionService.class);
        GroupsInfoCacheProvider groupInfoCacheProvider = BeanAccessor.getBean(GroupsInfoCacheProvider.class);
        GroupInfo4Cache gc = groupInfoCacheProvider.get(groupId);
        ChatSession cs = chatSessionService.selectGroupSession(gc.getGOwnerUserUid(), groupId);
        if (cs != null) {
            updateNotifyCount(cs.getNotifyCount() == null ? 0 + count : cs.getNotifyCount() + count);
        }
    }
}
